package lbservice

/*
Copyright 2021-2025 The k8gb Contributors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Generated by GoLic, for more details see: https://github.com/AbsaOSS/golic
*/

import (
	"testing"

	k8gbv1beta1 "github.com/k8gb-io/k8gb/api/v1beta1"
	"github.com/k8gb-io/k8gb/controllers/utils"
	"github.com/stretchr/testify/assert"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestGetServers(t *testing.T) {
	var tests = []struct {
		name            string
		serviceFile     string
		gslbAnnotations map[string]string
		expectedServers []*k8gbv1beta1.Server
		expectError     bool
	}{
		{
			name:        "valid LoadBalancer service with hostname annotation",
			serviceFile: "./testdata/lb_service_multiple_ips.yaml",
			gslbAnnotations: map[string]string{
				hostnameAnnotation: "test.example.com",
			},
			expectedServers: []*k8gbv1beta1.Server{
				{
					Host: "test.example.com",
					Services: []*k8gbv1beta1.NamespacedName{
						{
							Name:      "test-service",
							Namespace: "test-namespace",
						},
					},
				},
			},
			expectError: false,
		},
		{
			name:            "missing hostname annotation",
			serviceFile:     "./testdata/lb_service_multiple_ips.yaml",
			gslbAnnotations: map[string]string{
				// Missing hostname annotation
			},
			expectedServers: nil,
			expectError:     true,
		},
		{
			name:        "empty hostname annotation",
			serviceFile: "./testdata/lb_service_multiple_ips.yaml",
			gslbAnnotations: map[string]string{
				hostnameAnnotation: "",
			},
			expectedServers: nil,
			expectError:     true,
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			// arrange
			service := utils.FileToService(test.serviceFile)
			resolver := ReferenceResolver{
				service: service,
				gslb: &k8gbv1beta1.Gslb{
					ObjectMeta: metav1.ObjectMeta{
						Annotations: test.gslbAnnotations,
					},
				},
			}

			// act
			servers, err := resolver.GetServers()

			// assert
			if test.expectError {
				assert.Error(t, err)
				assert.Nil(t, servers)
			} else {
				assert.NoError(t, err)
				assert.Equal(t, test.expectedServers, servers)
			}
		})
	}
}

func TestGetGslbExposedIPs(t *testing.T) {
	var tests = []struct {
		name                 string
		serviceFile          string
		gslbAnnotations      map[string]string
		parentZoneDNSServers utils.DNSList
		expectedIPs          []string
		expectError          bool
	}{
		{
			name:            "LoadBalancer service with multiple IPs",
			serviceFile:     "./testdata/lb_service_multiple_ips.yaml",
			gslbAnnotations: map[string]string{
				// No explicit IP annotation, should use service status
			},
			parentZoneDNSServers: utils.DNSList{},
			expectedIPs:          []string{"192.168.1.1", "192.168.1.2"},
			expectError:          false,
		},
		{
			name:            "LoadBalancer service with no IPs",
			serviceFile:     "./testdata/lb_service_no_ips.yaml",
			gslbAnnotations: map[string]string{
				// No explicit IP annotation, service has no IPs
			},
			parentZoneDNSServers: utils.DNSList{},
			expectedIPs:          []string{},
			expectError:          false,
		},
		{
			name:        "LoadBalancer service with explicit IP annotation",
			serviceFile: "./testdata/lb_service_multiple_ips.yaml",
			gslbAnnotations: map[string]string{
				"k8gb.io/exposed-ip-addresses": "10.0.0.1,10.0.0.2",
			},
			parentZoneDNSServers: utils.DNSList{},
			expectedIPs:          []string{"10.0.0.1", "10.0.0.2"},
			expectError:          false,
		},
		{
			name:        "LoadBalancer service with invalid IP annotation",
			serviceFile: "./testdata/lb_service_multiple_ips.yaml",
			gslbAnnotations: map[string]string{
				"k8gb.io/exposed-ip-addresses": "invalid-ip,10.0.0.2",
			},
			parentZoneDNSServers: utils.DNSList{},
			expectedIPs:          []string{}, // ParseIPAddresses returns empty slice on error
			expectError:          true,
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			// arrange
			service := utils.FileToService(test.serviceFile)
			resolver := ReferenceResolver{
				service: service,
				gslb:    &k8gbv1beta1.Gslb{},
			}

			// act
			ips, err := resolver.GetGslbExposedIPs(test.gslbAnnotations, test.parentZoneDNSServers)

			// assert
			if test.expectError {
				assert.Error(t, err)
				assert.Equal(t, test.expectedIPs, ips)
			} else {
				assert.NoError(t, err)
				assert.ElementsMatch(t, test.expectedIPs, ips)
			}
		})
	}
}
